4.1 LQR
0. 前言
1.1 从"能控"到"最优"
控制理论的发展可以粗略地划分为两个阶段:
- 经典控制(PID 为代表):不依赖数学模型,靠误差反馈来调节。简单好用,但在多变量耦合系统上捉襟见肘。
- 现代控制(状态空间方法):基于系统的数学模型,直接操纵系统的内部状态。
在现代控制中,设计一个控制器通常意味着:给定系统
四旋翼飞行器属于高阶多变量非线性系统,传统PID控制需采用多层控制环级联结构以实现最终控制目标。然而,各层环路之间耦合较强,参数整定过程复杂,不仅需要针对每一层单独调节,还高度依赖工程师的调参经验或相似系统的参数参考。因此,当设计新型四旋翼飞行器时,参数调节往往耗时较长,且难以保证所得参数为全局最优。
最优控制则提供了另一种思路:不再依赖人工经验逐一调试参数,而是通过定义代价函数,由数学优化方法直接求解使代价最小化的最优参数
1.2 LQR 在控制界的地位
在控制算法的"知名度排行榜"上,PID 毫无争议排第一,而 LQR 大概能排到第二。它几乎出现在每一本现代控制理论的教材中,也是实际工程中应用最广泛的最优控制方法之一。
LQR 的全称是 Linear Quadratic Regulator(线性二次型调节器),这三个词各有含义:
| 词 | 含义 |
|---|---|
| Linear(线性) | 控制对象的动力学必须是线性的(或已被线性化) |
| Quadratic(二次型) | 用来衡量"好坏"的代价函数是二次型函数 |
| Regulator(调节器) | 控制目标是将状态调节到零(即消除误差) |
简单来说:LQR 是一种基于线性模型、通过最小化二次型代价函数来得到最优状态反馈增益的方法。
读完本文后,你将能够:
- 理解最优控制的基本思想:从"手动调参"到"定义代价函数,数学自动求解"
- 写出连续时间和离散时间的 LQR 代价函数,理解
(状态权重)和 (控制权重)的物理含义 - 使用 Python(SciPy)求解代数 Riccati 方程,一步得到最优反馈增益矩阵
- 运用 Bryson 法则为四旋翼选择合适的
、 初始值,并通过仿真迭代调优 - 理解 LQR 的稳定性保证和鲁棒性优势(无穷增益裕度 + 60° 相位裕度)
- 了解 LQR 的进阶扩展方向(LQI 积分控制、增益调度、LQG)
目录
- 线性二次型最优控制问题
- 无限时域 LQR
- LQR 的鲁棒性
- LQR 的极限行为:Q 与 R 的博弈
- 离散时间 LQR
- 使用LQR算法来控制四旋翼飞行
- LQR 的调参实战
- LQR 的扩展:输出调节、跟踪与积分控制
- 总结与进阶方向
2. 线性二次型最优控制问题
2.1 问题的数学描述
考虑一个连续时间线性系统:
其中
我们定义一个性能指标(Performance Index,也叫代价函数 Cost Function):
最优控制问题的提法是:找一个控制序列
2.2 代价函数每一项的含义
第一项:
是状态权重矩阵( ,半正定) - 这一项衡量了状态偏离目标的程度。
越大,代价越高 对角线上每个元素的大小,代表了对应状态的"重要性" - 比如对于一个 3 维系统,
意味着第三个状态分量最重要:控制器会优先让它收敛
第二项:
是控制权重矩阵( ,正定) - 这一项衡量了控制输入的大小。
越大,代价越高 必须是正定的:因为任何非零的控制输入都应该消耗能量、产生代价
第三项:
- 强调在最终时刻
状态也要尽量小 - 在无限时域问题中这一项会消失(后面会解释)
2.3 有限时域 LQR 的解
对于有限时域问题(
其中
有限时域 LQR 的求解比较麻烦:
3. 无限时域 LQR
3.1 从有限到无限
一个重要的发现是:当
对于线性定常系统:
定义无限时域代价函数(终端项因
这就是我们常说的 Infinite Horizon LQR,也是工程实践中最常用的 LQR 形式。
3.2 代数 Riccati 方程
在无限时域下,原本的 Riccati 微分方程退化为代数 Riccati 方程(Algebraic Riccati Equation, ARE):
解出
控制律为:
3.3 求解流程总结
对于使用者来说,LQR 的求解过程可以归纳为三步:
- 建立系统的状态空间模型,得到
和 矩阵 - 根据控制目标,选择合适的权重矩阵
和 - 求解 ARE 得到
,然后计算
在工具层面:
MATLAB:
一步到位,直接返回增益矩阵 。 Python(SciPy):使用
scipy.linalg.solve_continuous_are分两步完成:pythonfrom scipy.linalg import solve_continuous_are P = solve_continuous_are(A, B, Q, R) # 求解连续 ARE,得到 P 矩阵 K = np.linalg.inv(R) @ B.T @ P # 由 P 计算反馈增益 Ksolve_continuous_are函数简介:项目 说明 做了什么 求解连续时间代数 Riccati 方程 输入 ( 状态矩阵)、 ( 输入矩阵)、 ( 状态权重)、 ( 控制权重) 输出 ( 对称正定矩阵):Riccati 方程的解 在工程中的角色 它是 LQR 设计流程的"最终计算步":你负责提供模型 和设计意图 ,这个函数替你完成繁重的矩阵方程求解 函数内部使用的数值算法基于 QR/QZ 分解等成熟的线性代数技术,保证了求解的数值稳定性。调用者不需要理解这些细节,只需确认输入矩阵维度正确、
能控、 正定即可。
3.4 LQR 的稳定性保证
Infinite Horizon LQR 有一些重要的理论保证:
- 系统必须是能控的(
可控),否则无法保证所有状态都能被驱动到零。 - 闭环系统是渐进稳定的,即
的所有特征值实部均为负。 - 如果
是可观测的,或者 ,则闭环稳定性有严格保证。
这些条件听起来可能较为抽象,但对于大多数实际的物理系统(包括四轴飞行器),它们都是自然满足的。
3.5 与 PID 的对比
LQR 和 PID 代表了两种截然不同的控制设计哲学:
| PID | LQR | |
|---|---|---|
| 结构 | 级联结构(外环+内环),需要为每个通道单独设计 | 全状态反馈,一个 |
| 调参方式 | 依赖工程经验逐层调参,通道间耦合相互影响 | 建立模型后,数学直接算出最优 |
| 参数个数 | 每层 3 个参数 × 多个通道(位置环3通道 + 姿态环3通道) → 参数数量快速增长 | 通过 Q 和 R 两个权重矩阵统一调整,参数有清晰的物理对应 |
| 耦合处理 | 手动处理,依赖工程师经验 | 自动处理所有交叉耦合 |
| 最优性 | 无 | 在给定 Q、R 下使代价函数取极小值 |
| 鲁棒性 | 依赖设计水平 | 有理论保证(无穷增益裕度 + 60° 相位裕度) |
LQR 的优势在于:将"手动逐个调参"转变为"定义性能指标 → 数学自动求解"。工程师不再需要纠结于每个通道的 P/I/D 增益怎么设,而是回答一个更直观的问题:"我更在意位置精度,还是更在意省电?"
4. LQR 的鲁棒性
LQR 除了"最优"之外,还有一个经常被忽略但非常重要的优点:出色的鲁棒性。
4.1 增益裕度:无穷大
考虑在控制输入的每个通道上乘以一个增益系数
系统就依然稳定。换言之:
- 增益可以任意增大而不会失稳(无穷大增益裕度)
- 增益减小到原来的 50% 仍然稳定(至少 50% 的增益衰减裕度)
需要说明的是:上述结论针对的是每个输入通道独立的对角增益变化(
, ),而非任意形式的跨通道矩阵增益扰动。实际工程中如果各通道之间存在耦合的增益偏差(比如 , 为非对角矩阵),这一结论并不直接适用。
4.2 相位裕度:至少 60°
LQR 在每个输入通道上具有至少 ±60° 的相位裕度。这意味着即使反馈信号存在时间延迟或相位滞后,LQR 控制器仍有很大的容忍空间。
4.3 为什么这很重要
鲁棒性意味着:你的模型不需要完美。即使实际的
5. LQR 的极限行为:Q 与 R 的博弈
理解 LQR 最关键的一点是认识
5.1 Control is Cheap:
当
- 你不在乎用了多少控制能量,你在意的只是状态误差要尽快消除
- LQR 会给出高增益,响应极快,状态迅速收敛
- 闭环极点会趋向于 Butterworth 模式分布在左半平面,远离虚轴
- 如果系统有右半平面零点,它们会被驱赶到无穷远
代价:控制量可能非常大,容易触发执行器饱和,对噪声也更敏感。
5.2 Control is Expensive:
当
- 你不愿意付出太多控制能量,你宁可让状态收敛得慢一些
- LQR 会给出低增益,响应平缓,控制量小
- 如果系统有开环不稳定极点,LQR 会以最小的控制量把它们搬到左半平面
- 如果系统开环稳定,增益会趋近于零,控制器几乎不干预
代价:响应很慢,状态误差较大。
5.3 实际中永远是折中
在真实的工程问题中,你永远在"控制很便宜"和"控制很昂贵"之间寻找平衡。没有一个放之四海皆准的
6. 离散时间 LQR
前面所有讨论都是基于连续时间系统
6.1 为什么需要离散化
你的控制器以固定周期
- 读取传感器数据
- 运行控制算法
- 输出控制指令
- 等待下一个周期
因此需要将连续模型
6.2 精确离散化:矩阵指数法
一种高精度的离散化方法是利用矩阵指数。构建增广矩阵:
计算:
其中左上角
这种方法比简单的欧拉近似
精度高得多,是工程标准做法。
6.3 离散代数 Riccati 方程
得到
离散反馈增益:
离散控制律:
Python 中使用 scipy.linalg.solve_discrete_are 求解:
from scipy.linalg import solve_discrete_are
S = solve_discrete_are(Ad, Bd, Q, R) # 求解离散 ARE,得到 P 矩阵
K = np.linalg.inv(Bd.T @ S @ Bd + R) @ (Bd.T @ S @ Ad) # 由 P 计算离散反馈增益solve_discrete_are 函数简介:
| 项目 | 说明 |
|---|---|
| 做了什么 | 求解离散时间代数 Riccati 方程 |
| 输入 | |
| 输出 | |
| 与连续版本的区别 | 方程形式不同(差分代替微分),但输入输出接口和函数用途完全一致。离散版本直接适配数字控制器的步进逻辑 |
这也是配套参考工程 lqr_controller.py 中实际使用的函数,工程中先对 solve_discrete_are 求解离散反馈增益
7. 使用LQR算法来控制四旋翼飞行
有了前面的理论基础,现在我们来看一个具体的应用:用 LQR 实现四轴飞行器的定点悬停控制。
7.1 为什么 LQR 较为适合四轴飞行器
四轴飞行器是一个典型的多输入多输出(MIMO)系统:
- 4 个控制输入:四个电机的推力
- 12 个状态量:3 姿态角 + 3 角速度 + 3 位置 + 3 速度
- 强耦合:姿态和位置之间有动力学耦合(飞行器要平移必须先倾斜)
如果用 PID,你需要为每个通道单独设计控制器,还要想办法处理通道间的交叉耦合。而 LQR 天然适合这种场景:全状态反馈自动处理所有耦合关系,Q 和 R 矩阵提供了统一的调参入口。
7.2 建立状态空间模型
这是整个 LQR 设计中最关键的一步,主要是构建四旋翼物理模型的线性近似,这部分我们已经在之前的教程中详细讲解过,我们在这里再回顾一下。
状态向量(12 维):
| 符号 | 含义 | 单位 |
|---|---|---|
| 滚转、俯仰、偏航角 | rad | |
| 三轴角速度 | rad/s | |
| 世界坐标系位置 | m | |
| 机体坐标系速度 | m/s |
关于坐标系不一致的说明:这里位置使用世界坐标系、速度使用机体坐标系,并非疏忽。
严格来说,位置的变化率
是世界坐标系下的速度 ,而状态中存储的是机体坐标系速度 ,两者通过旋转矩阵关联: (其中 是机体→世界的旋转矩阵,由欧拉角 决定)。 在本工程的小角度假设下(
,且偏航角 也被控制在 0 附近), ,因此 ,两种速度近似相等。这样做的目的是简化线性模型的构建:省去了旋转矩阵在 A 矩阵中引入的复杂耦合项,使 LQR 设计更加简洁直接。 如果偏航角不接近 0,则需要先将机体速度旋转变换到世界坐标系后再参与位置计算,或者在偏航通道使用独立的坐标系处理。
控制向量(4 维):
系统矩阵
- 姿态运动学(第 0-2 行):
,角度变化率等于角速度 - 位置运动学(第 6-8 行):
,在世界坐标系下,位置的变化率应为世界坐标系速度 ,但在 的小角度假设下 (机体速度),因此这里直接用机体速度近似。Z 方向不受偏航角影响,严格成立 - 姿态-位置耦合(第 9-10 行):
,这是多旋翼飞行最本质的动力学关系:倾斜产生水平加速度。此处姿态角的正方向定义为: 时机头向下俯(前倾), 时机身向右滚转(与 MuJoCo 坐标系约定一致)。在此约定下,前倾时重力沿机体 X 轴的正向分量 产生向前的水平加速度,右倾时重力沿机体 Y 轴的负向分量 产生向左的水平加速度。 在这里充当了"角度→加速度"的转换系数。
其余行(角速度行 3-5、Z 速度行 11)全为零,这些状态的变化完全由控制输入
输入矩阵
| 行 | 影响 | 物理公式 |
|---|---|---|
| 3 ( | Roll 角加速度 | |
| 4 ( | Pitch 角加速度 | |
| 5 ( | Yaw 角加速度 | |
| 11 ( | Z 轴加速度 |
正负号由电机的安装位置和旋转方向决定(X 型四轴构型)。
7.3 Q 和 R 的选择:Bryson 法则
对于初学者来说,选择 Q 和 R 可能感觉很"玄学"。Bryson 法则提供了一个很好的起点:
例如,如果你认为位置误差不应超过 1m,则
参考工程中的实际
- 滚转/俯仰角权重:5.0(姿态纠正比较积极)
- 偏航角权重:10.0(偏航纠正最积极)
- 角速度权重:0.1(允许角速度有一定波动,相当于增加阻尼)
- 位置权重:1.0(中等精度要求)
- 速度权重:0.1(阻尼项,防止速度超调)
- 控制权重
:100.0(推力变化偏保守,优先保证平滑)
7.4 实际工程中的额外设计
理论上的 LQR 只需
悬停前馈:LQR 计算的是增量控制
最终输出为
控制限幅:LQR 不关心电机的物理极限,所以需要手动限幅:
预测补偿(工程技巧,非 LQR 理论本身):电机有响应延迟(一阶惯性,时间常数
注意:这一步并非 LQR 的标准组成部分。如果采样率足够高(控制周期远小于执行器时间常数),或者执行器响应足够快,这一步可以省略,直接用当前状态反馈即可。盲目照搬但预测步数与实际延迟不匹配,反而可能引入额外的模型误差。
连续模型离散化:控制器以固定频率运行(参考工程中为 400Hz,
8. LQR 的调参实战
8.1 增量调参策略
- 用 Bryson 法则确定 Q 和 R 的初始值
- 运行仿真,观察各状态的时域响应
- 某个状态收敛太慢 → 增大对应的 Q 值
- 控制量振荡或频繁饱和 → 增大 R 值
- 某状态超调严重 → 增大其对应的导数项权重(角速度/速度)来增加阻尼
- 重复 2-5 直到满意
8.2 常见问题速查
| 现象 | 可能原因 | 调整方向 |
|---|---|---|
| 响应太慢 | Q 太小或 R 太大 | 增大 Q / 减小 R |
| 超调振荡 | 阻尼不足 | 增大角速度/速度权重 |
| 控制量饱和 | R 太小 | 增大 R |
| 稳态误差 | 有未建模扰动 | 考虑加积分项(LQI) |
| 某通道耦合异常 | 线性化不准 | 检查模型参数 |
9. LQR 的扩展:输出调节、跟踪与积分控制
基本的 LQR(Infinite Horizon Regulator)做的是"把状态调节到零"。但在实际应用中,我们往往需要更多功能。
9.1 输出调节(Output LQR)
如果我们关心的不是全部状态,而是某些输出
只需将原来的
9.2 从定点调节到轨迹跟踪
LQR 的默认假设是将状态调节到零。但在实际应用中,我们通常需要跟踪非零的目标。根据目标的特性,有三种不同的处理方式:
(1)定点调节(Setpoint Tracking)
如果目标状态
这里
(2)严格时变轨迹跟踪(Finite-Horizon LQR)
如果目标
(3)增益调度(Gain Scheduling):工程近似
对于大范围机动的非线性系统,一种工程简化做法是:在状态空间的多个工作点分别线性化并计算对应的固定增益
总结:定点跟踪 → 常值
,时变轨迹严格解 → 有限时域 LQR 得 ,大范围非线性机动 → 增益调度(工程近似)。三种方式的适用场景和理论严格性各不相同,不可混为一谈。
9.3 在 LQR 中引入积分控制(LQI)
标准 LQR 没有积分作用,可能产生稳态误差。解决方法是将积分器状态扩充到系统状态中:
定义积分误差
然后对这个增广系统设计 LQR,得到的
这个思路说明:LQR 与积分控制、MPC 等方法可以自然地融合。LQR 提供的不是一个孤立的控制器,而是一个可以灵活扩展的控制设计框架。
10. 总结与进阶方向
10.1 核心要点
- LQR 是一种最优状态反馈控制:不指定极点,而是通过最小化代价函数来求
- 代价函数
: 控制性能追求, 控制能量代价 - 求解核心是代数 Riccati 方程:MATLAB 的
lqr()或 Python 的solve_continuous_are()一步搞定 - LQR 有极好的鲁棒性:无穷增益裕度 + 60° 相位裕度
- 离散化是工程必需:用矩阵指数法精确离散化,再用离散 ARE 求解
- 调参从 Bryson 法则出发:跑仿真,观察,迭代调整
10.2 LQR 的局限
- 只适用于线性系统(非线性系统需要先线性化)
- 需要全状态可测或可估计(实际中常配合 Kalman 滤波器)
- 模型精度直接影响控制效果
- 标准形式没有积分作用(可通过 LQI 扩展)
本章参考资料与引申阅读已汇总至 参考资料。
